import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:h_flutter_119/api/Api.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';

class HttpUtils {
  static HttpUtils? instance;

  BaseOptions? options;
  Dio? dio;
  CancelToken cancelToken = CancelToken();

  static HttpUtils getInstance() {
    return instance ??= HttpUtils();
  }

  HttpUtils({String baseUrl = Api.BASE_URL}) {
    options = BaseOptions(
      baseUrl: baseUrl,
      connectTimeout: const Duration(seconds: 10),
      receiveTimeout: const Duration(seconds: 5),
      headers: {'version': "1.0.0"},
      //请求的Content-Type，默认值是"application/json; charset=utf-8",Headers.formUrlEncodedContentType会自动编码请求体.
      contentType: Headers.formUrlEncodedContentType,
      //表示期望以那种格式(方式)接受响应数据。接受四种类型 `json`, `stream`, `plain`, `bytes`. 默认值是 `json`,
      responseType: ResponseType.plain,
    );

    dio = Dio(options);

    //Cookie管理
    final cookieJar = CookieJar();
    dio?.interceptors.add(CookieManager(cookieJar));
    dio?.interceptors.add(PrettyDioLogger(
      // 添加日志格式化工具类
      requestHeader: true,
      requestBody: true,
      responseBody: true,
      responseHeader: false,
      compact: false,
    ));
    //添加拦截器
    dio?.interceptors.add(InterceptorsWrapper(
        onRequest: (RequestOptions options, RequestInterceptorHandler handler) {
      print("请求之前 header = ${options.headers.toString()}");
      // 如果你想完成请求并返回一些自定义数据，你可以使用 `handler.resolve(response)`。
      // 如果你想终止请求并触发一个错误，你可以使用 `handler.reject(error)`。
      return handler.next(options); //continue
    }, onResponse: (Response response, ResponseInterceptorHandler handler) {
      print("响应之前");
      // 如果你想终止请求并触发一个错误，你可以使用 `handler.reject(error)`。
      return handler.next(response); // continue
    }, onError: (DioException e, ErrorInterceptorHandler handler) {
      print("错误之前");
      // 如果你想完成请求并返回一些自定义数据，你可以使用 `handler.resolve(response)`。
      return handler.next(e);
    }));

    // 在调试模式下需要抓包调试，所以我们使用代理，并禁用HTTPS证书校验
    if (Api.PROXY_ENABLE) {

    }

  }

  //TODO just测试并发请求
  Future<dynamic> asyncRequest(String path,{data}) async{
    var response = await dio?.get(path,queryParameters: data);
    return response;
  }

  /// GET请求
  get(String path, {data, options, cancleToken}) async {
    Response? response;
    try {
      response = await dio?.get(path,
          queryParameters: data, options: options, cancelToken: cancleToken);
      print('get success---------${response?.statusCode}');
      print('get success---------${response?.data}');
    } on DioException catch (e) {
      print('get error---------$e');
      formatError(e);
    }
    return response;
  }

  /// POST
  post(String path,{data,options,cancleToken}) async{
    Response? response;
    try{
      response = await dio?.post(path,queryParameters: data,options: options,cancelToken: cancleToken);
      print('post success---------${response?.data}');
    }on DioException catch(e){
      print('post error---------$e');
      formatError(e);
    }
    return response;
  }

  /*
   * error统一处理
   */
  void formatError(DioException e) {
    if (e.type == DioExceptionType.connectionTimeout) {
      // It occurs when url is opened timeout.
      print("连接超时");
    } else if (e.type == DioExceptionType.sendTimeout) {
      // It occurs when url is sent timeout.
      print("请求超时");
    } else if (e.type == DioExceptionType.receiveTimeout) {
      //It occurs when receiving timeout
      print("响应超时");
    } else if (e.type == DioExceptionType.badResponse) {
      // When the server response, but with a incorrect status, such as 404, 503...
      print("出现异常");
    } else if (e.type == DioExceptionType.cancel) {
      // When the request is cancelled, dio will throw a error with this type.
      print("请求取消");
    } else {
      //DEFAULT Default error type, Some other Error. In this case, you can read the DioError.error if it is not null.
      print("未知错误");
    }
  }
}
